/**
 * Copyright 2013 wasu.com
 *
 *
 * Create on 2014-7-29 下午11:52:45
 */
package xiaojian.toolkit.netty.handler.codec.tcp.encode;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import xiaojian.toolkit.bean.CommonsHeader;
import xiaojian.toolkit.bean.json.annotation.JSONMessage;
import xiaojian.toolkit.util.Identifier;
import xiaojian.toolkit.util.IdentifierFactory;
import xiaojian.toolkit.util.MutableIdentifyable;

/**
 * 将需要发送的对象，编码为头为xipheader、正文为json的数据流，方便在网络上传输。
 * 
 * @author <a href="mailto:caoxiaojian@wasu.com>xiaojian.cao</a>
 * 
 */
public abstract class MixedJsonEncoder extends MessageToByteEncoder<MutableIdentifyable> {

	private static final Logger logger = LoggerFactory
			.getLogger(MixedJsonEncoder.class);

	/**
	 * @see io.netty.handler.codec.MessageToByteEncoder#encode(io.netty.channel.ChannelHandlerContext,
	 *      java.lang.Object, io.netty.buffer.ByteBuf)
	 */
	@Override
	protected void encode(ChannelHandlerContext ctx, MutableIdentifyable msg,
			ByteBuf out) throws Exception {
		JSONMessage jm = msg.getClass().getAnnotation(JSONMessage.class);
		if (jm == null) {
			throw new RuntimeException(
					"invalid json message, missing @JSONMessage.");
		}

		int msgCode = jm.messageCode();
		if (msgCode == 0) {
			throw new RuntimeException(
					"invalid json message, missing msgCode.");
		}
		
		final Identifier<?> id = ((MutableIdentifyable) msg).getIdentification();
		if (logger.isDebugEnabled()) {
			logger.debug("encoding JSONObject {} to wrappedBuffer", msg);
		}
		
		if (null == id && logger.isWarnEnabled()) {
			logger.warn("{} is json but missing transactionId", msg);	
		}
		

		final String jsonString = buildJson(msg);
		final byte[] jsonBytes = jsonString.getBytes("UTF-8");
		
		if (logger.isDebugEnabled()) {
			logger.debug("jsonString -> {}", jsonString);
		}
		
		// -- 组装头
		CommonsHeader header = new CommonsHeader();
		header.setMessageCode(msgCode);
		header.setIdBytes(IdentifierFactory.gerIdByte(id));;
		header.setMessageLength(jsonBytes.length);
		header.setMessageCode(msgCode);
		
		if (logger.isDebugEnabled()) {
			logger.debug("header -> {}", header);
		}
		
		// -- 写入数据。
		out.writeByte(header.getBasicVer());
		out.writeShort(header.getPayloadType());
		out.writeShort(header.getType());
		out.writeBytes(header.getIdBytes());
		out.writeInt(header.getReserved());
		out.writeInt(header.getMessageCode());
		out.writeInt(header.getMessageLength());
		out.writeBytes(jsonBytes);
		
	}
	
	protected abstract String buildJson(Object msg);

}
